package com.shiloop.sensorsampler;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by Baofeng on 2015/1/6.
 */
public class WaveView extends View {
    public static final int MAX_LENGTH = 300;

    private Paint mLinePainter;

    private final Object mDataLock = new Object();

    private float mDx = 0.0f;

    private float mPoints[];

    private float mSource[];

    private float mMax;

    public WaveView(Context context) {
        super(context);
        init();
    }

    public WaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public WaveView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        mPoints = new float[MAX_LENGTH * 2];
        mSource = new float[MAX_LENGTH];
        mLinePainter = new Paint();
        for (int i = 1, j = 0; i < mPoints.length; i += 2, j++) {
            mPoints[i] = 0;
            mSource[j] = 0;
        }
        mMax = 0.0f;

        mLinePainter.setColor(Color.BLACK);
        mLinePainter.setStrokeWidth(2.0f);
    }

    public void reset() {
        synchronized (mDataLock) {
            for (int i = 1, j = 0; i < mPoints.length; i += 2, j++) {
                mPoints[i] = 0;
                mSource[j] = 0;
            }
            mMax = 0.0f;
        }
        invalidate();
    }

    public void add(float y) {
        synchronized (mDataLock) {
            for (int i = 1; i < mSource.length; i++) {
                mSource[i - 1] = mSource[i];
            }
            mSource[mSource.length - 1] = y;
            mMax = Math.max(mMax, Math.abs(y));
            if (mMax == 0.0f) {
                mMax = 1.0f;
            }
        }
        invalidate();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth() - getPaddingLeft() - getPaddingRight();
        int height = getHeight() - getPaddingBottom() - getPaddingTop();

        boolean isRecalculate = false;

        if (mPoints[mPoints.length - 2] == 0.0f) {
            isRecalculate = true;
        }

        // init x array
        float dx = ((float) width) / MAX_LENGTH;
        if (isRecalculate || Math.abs(mDx - dx) > 0.5) {
            mDx = dx;
            isRecalculate = true;
        }
        // calculate x array
        if (isRecalculate) {
            float x = getPaddingLeft();
            for (int i = 0; i < mPoints.length; i += 2) {
                mPoints[i] = x;
                x += mDx;
            }
        }
        float h = height / 2.0f;
        float traction = h / mMax;

        float miny = getPaddingTop() + h;

        // initial y array
        synchronized (mDataLock) {
            for (int i = 0; i < mSource.length; i++) {
                mPoints[2 * i + 1] = mSource[i] * traction + miny;
            }
        }
        canvas.drawPoints(mPoints, mLinePainter);
    }
}
